package com.zhiche.wms.service.stockinit.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.SysSourceEnum;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.supports.enums.UomEnum;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.stockinit.StockInitHeaderMapper;
import com.zhiche.wms.domain.mapper.stockinit.StockInitLineMapper;
import com.zhiche.wms.domain.model.base.StoreLocation;
import com.zhiche.wms.domain.model.base.Storehouse;
import com.zhiche.wms.domain.model.stock.StockProperty;
import com.zhiche.wms.domain.model.stockinit.StockInitHeader;
import com.zhiche.wms.domain.model.stockinit.StockInitLine;
import com.zhiche.wms.dto.stockinit.StockInitImportDTO;
import com.zhiche.wms.dto.stockinit.StockInitQueryListResultDTO;
import com.zhiche.wms.service.base.IBusinessDocNumberService;
import com.zhiche.wms.service.base.IStoreLocationService;
import com.zhiche.wms.service.base.IStorehouseService;
import com.zhiche.wms.service.stock.impl.StockServiceImpl;
import com.zhiche.wms.service.stockinit.IStockInitHeaderService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 期初库存头 服务实现类
 * </p>
 *
 * @author qichao
 * @since 2018-05-30
 */
@Service
public class StockInitHeaderServiceImpl extends ServiceImpl<StockInitHeaderMapper, StockInitHeader> implements IStockInitHeaderService {

    @Autowired
    private SnowFlakeId snowFlakeId;
    @Autowired
    private IStoreLocationService locationService;
    @Autowired
    private StockInitLineServiceImpl stockInitLineService;
    @Autowired
    private StockServiceImpl stockService;
    @Autowired
    private IBusinessDocNumberService numberService;
    @Autowired
    private IStorehouseService storehouseService;
    @Autowired
    private StockInitLineMapper lineMapper;

    @Override
    @Transactional
    public boolean createStockInit(StockInitHeader stockInitHeader) {
        stockInitHeader.setId(snowFlakeId.nextId());
        for (StockInitLine ml : stockInitHeader.getStockInitLineList()) {
            ml.setId(snowFlakeId.nextId());
            ml.setHeaderId(stockInitHeader.getId());
            stockInitLineService.insert(ml);
        }
        stockInitHeader.setLineCount(stockInitHeader.getStockInitLineList().size());
        stockInitHeader.setStatus("10");
        return insert(stockInitHeader);
    }

    /**
     * 审核 期初库存
     */
    @Override
    @Transactional
    public boolean auditStockInit(Long stockInitId) {

        StockInitHeader stockInitHeader = selectById(stockInitId);
        if (Objects.isNull(stockInitHeader)) throw new BaseException(4010, "期初库存不存在！");

        EntityWrapper<StockInitLine> ew = new EntityWrapper<>();
        ew.eq("header_id", stockInitHeader.getId());
        List<StockInitLine> stockInitLineList = stockInitLineService.selectList(ew);
        if (Objects.isNull(stockInitLineList)) throw new BaseException(4020, "期初库存明细不存在！");

        for (StockInitLine ml : stockInitLineList) {
            updateStockQty(stockInitHeader.getStoreHouseId(), ml);
        }
        stockInitHeader.setStatus("20");
        stockInitHeader.setGmtCreate(null);//创建时间使用数据库自行处理
        stockInitHeader.setGmtModified(null);//更新时间使用数据库自行处理
        return updateById(stockInitHeader);
    }

    /**
     * 创建并审核期初库存
     */
    @Override
    @Transactional
    public boolean createAndAuditStockInit(StockInitHeader stockInitHeader) {

        stockInitHeader.setId(snowFlakeId.nextId());
        for (StockInitLine ml : stockInitHeader.getStockInitLineList()) {
            ml.setId(snowFlakeId.nextId());
            ml.setHeaderId(stockInitHeader.getId());
            if (stockInitLineService.insert(ml)) {
                updateStockQty(stockInitHeader.getStoreHouseId(), ml);
            } else {
                throw new BaseException("保存移位单明细失败！");
            }
        }
        stockInitHeader.setLineCount(stockInitHeader.getStockInitLineList().size());
        stockInitHeader.setStatus("20");
        return insert(stockInitHeader);
    }

    @Override
    @Transactional
    public boolean cancelAuditStockInit(Long stockInitId) {
        StockInitHeader stockInitHeader = selectById(stockInitId);
        if (Objects.isNull(stockInitHeader)) throw new BaseException(4010, "期初库存不存在！");

        EntityWrapper<StockInitLine> ew = new EntityWrapper<>();
        ew.eq("header_id", stockInitHeader.getId());
        List<StockInitLine> stockInitLineList = stockInitLineService.selectList(ew);
        if (Objects.isNull(stockInitLineList)) throw new BaseException(4020, "期初库存明细不存在！");

        for (StockInitLine ml : stockInitLineList) {
            cancelStockQty(stockInitHeader.getStoreHouseId(), ml);
        }
        stockInitHeader.setStatus("30");
        stockInitHeader.setGmtCreate(null);//创建时间使用数据库自行处理
        stockInitHeader.setGmtModified(null);//更新时间使用数据库自行处理
        return updateById(stockInitHeader);
    }

    /**
     * 导入期初库存
     */
    @Override
    public Map<String, JSONArray> saveImportStockInitNew(String data) {
        if (StringUtils.isBlank(data)) {
            throw new BaseException("导入数据为空");
        }
        JSONObject jsonObject = JSONObject.parseObject(data);
        JSONArray arrayHeader = JSONObject.parseArray(jsonObject.getString("header"));
        JSONArray arrayRows = JSONObject.parseArray(jsonObject.getString("rows"));
        if (CollectionUtils.isEmpty(arrayHeader)) {
            throw new BaseException("导入数据为空");
        }
        if (CollectionUtils.isEmpty(arrayRows)) {
            throw new BaseException("导入数据为空");

        }
        if (!arrayHeader.get(arrayHeader.size() - 1).equals("备注")) {
            arrayHeader.add("导入结果");
            arrayHeader.add("备注");
        }

        HashMap<String, Long> whCache = Maps.newHashMap();
        Map<String, JSONArray> map = new HashMap<>();

        for (int i = 0; i < arrayRows.size(); i++) {
            checkAndInsertData(arrayRows, whCache, i);
        }
        map.put("header", arrayHeader);
        map.put("rows", arrayRows);
        return map;
    }


    /**
     * 查询期初库存列表
     */
    @Override
    public Page<StockInitQueryListResultDTO> queryStockPage(Page<StockInitQueryListResultDTO> page) {
        if (page == null) {
            throw new BaseException("参数不能为空");
        }
        Wrapper<StockInitQueryListResultDTO> wp = new EntityWrapper<>();
        Map cd = page.getCondition();
        if (cd != null) {
            if (Objects.nonNull(cd.get("ownerId")) &&
                    StringUtils.isNotBlank(cd.get("ownerId").toString())) {
                wp.eq("owner_id", cd.get("ownerId").toString());
            }
            if (Objects.nonNull(cd.get("styleName")) &&
                    StringUtils.isNotBlank(cd.get("styleName").toString())) {
                wp.eq("materiel_code", cd.get("styleName").toString());
            }
            if (Objects.nonNull(cd.get("lotNo1")) &&
                    StringUtils.isNotBlank(cd.get("lotNo1").toString())) {
                String[] split = cd.get("lotNo1").toString().split(",");
                List<String> vins = Arrays.asList(split);
                wp.in("lot_no1", vins).orNew().like("lot_no1", cd.get("lotNo1").toString());
            }
            if (Objects.nonNull(cd.get("houseId")) &&
                    StringUtils.isNotBlank(cd.get("houseId").toString())) {
                wp.eq("store_house_id", cd.get("houseId").toString());
            }
        }
        wp.orderBy("gmt_create", Boolean.FALSE)
                .orderBy("lineId", Boolean.TRUE);
        List<StockInitQueryListResultDTO> data = lineMapper.queryInitPage(page, wp);
        page.setRecords(data);
        return page;
    }

    private void checkAndInsertData(JSONArray arrayRows, HashMap<String, Long> whCache, int i) {
        StockInitImportDTO dto = new StockInitImportDTO();
        dto.setLotNo1(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("车架号*")) ?
                null : arrayRows.getJSONObject(i).getString("车架号*").trim());
        dto.setCustomerName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("客户名称*")) ?
                null : arrayRows.getJSONObject(i).getString("客户名称*").trim());
        //dto.setMaterielName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("车型名称*")) ?
        //        null : arrayRows.getJSONObject(i).getString("车型名称*"));
        dto.setMaterielId(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("车型名称*")) ?
                null : arrayRows.getJSONObject(i).getString("车型名称*"));
        dto.setWarehouseName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("仓库名称*")) ?
                null : arrayRows.getJSONObject(i).getString("仓库名称*").trim());
        dto.setLocationCode(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("库位编码*")) ?
                null : arrayRows.getJSONObject(i).getString("库位编码*").trim());
        dto.setQty(arrayRows.getJSONObject(i).getBigDecimal("数量*"));
//        dto.setUom(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("计量单位")) ?
//                null : arrayRows.getJSONObject(i).getString("计量单位").trim());
        dto.setMaterielName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("车型描述/物料名称")) ?
                null : arrayRows.getJSONObject(i).getString("车型描述/物料名称").trim());
        dto.setLotNo2(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("物料编码")) ?
                null : arrayRows.getJSONObject(i).getString("物料编码").trim());
        dto.setLotNo3(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("颜色编码")) ?
                null : arrayRows.getJSONObject(i).getString("颜色编码").trim());
        dto.setLotNo4(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("车型编码")) ?
                null : arrayRows.getJSONObject(i).getString("车型编码").trim());

        StringBuilder sb = new StringBuilder();
        String vin = dto.getLotNo1();
        String materielId = dto.getMaterielId();
        String warehouseName = dto.getWarehouseName();
        String customerName = dto.getCustomerName();
        String locationCode = dto.getLocationCode();
        BigDecimal qty = dto.getQty();
        if (StringUtils.isBlank(vin)) {
            sb.append("车架号为空;");
        }
        if (StringUtils.isBlank(materielId)){
            sb.append("车型名称为空;");
        }
        if (StringUtils.isBlank(warehouseName)) {
            sb.append("仓库为空;");
        }
        if (StringUtils.isBlank(customerName)) {
            sb.append("客户名称为空;");
        }
        if (StringUtils.isBlank(locationCode)) {
            sb.append("库位编码为空;");
        }
        if (qty == null) {
            sb.append("数量为空;");
        }
        //设置仓库id缓存map
        EntityWrapper<Storehouse> wrapper = new EntityWrapper<>();
        wrapper.eq("name", dto.getWarehouseName())
                .eq("status", TableStatusEnum.STATUS_10.getCode());
        Long houseId = whCache.get(dto.getWarehouseName());
        if (houseId == null) {
            List<Storehouse> storehouses = storehouseService.selectList(wrapper);
            if (CollectionUtils.isNotEmpty(storehouses)) {
                whCache.put(dto.getWarehouseName(), storehouses.get(0).getId());
                houseId = storehouses.get(0).getId();
            } else {
                //未找到仓库--提示错误
                sb.append("未找到仓库名称").append(dto.getWarehouseName()).append("信息;");
            }
        }
        List<StoreLocation> locations = null;
        if (houseId != null) {
            //查询库位
            EntityWrapper<StoreLocation> lwp = new EntityWrapper<>();
            lwp.eq("code", dto.getLocationCode())
                    .eq("store_house_id", whCache.get(dto.getWarehouseName()))
                    .eq("status", TableStatusEnum.STATUS_10.getCode());
            locations = locationService.selectList(lwp);
            if (CollectionUtils.isEmpty(locations)) {
                sb.append("未查询到对应仓库id:").append(whCache.get(dto.getWarehouseName()))
                        .append("库位码:").append(dto.getLocationCode()).append("库位信息;");
            }
        }

        if (houseId != null
                && StringUtils.isNotBlank(vin)) {
            //重复性校验 前提仓库id 不能为空
            HashMap<String, Object> params = Maps.newHashMap();
            params.put("houseId", houseId);
            params.put("vin", vin);
            int count = countInitStockByParam(params);
            if (count > 0) {
                sb.append("车架号").append(dto.getLotNo1()).append("已经存在;");
            }
        }
        if (StringUtils.isNotBlank(sb)) {
            arrayRows.getJSONObject(i).put("导入结果", "失败");
            arrayRows.getJSONObject(i).put("备注", sb.toString());
        } else {
            try {
                ArrayList<StockInitLine> insertLines = Lists.newArrayList();
                StockInitHeader sih = new StockInitHeader();
                StockInitLine sil = new StockInitLine();
                sih.setId(snowFlakeId.nextId());
                sih.setInitNo(numberService.getStockInitNo());
                sih.setStoreHouseId(whCache.get(dto.getWarehouseName()));
                sih.setOwnerId(dto.getCustomerName());
                sih.setOrderDate(new Date());
                // 设置为已审核状态
                sih.setStatus(TableStatusEnum.STATUS_20.getCode());
                sih.setLineCount(1);
                sih.setSumQty(dto.getQty());
                sih.setUserCreate(SysSourceEnum.IMPORT.getName());
                sih.setUserModified(SysSourceEnum.IMPORT.getName());
                sil.setId(snowFlakeId.nextId());
                sil.setHeaderId(sih.getId());
                sil.setOwnerId(dto.getCustomerName());
                if(org.springframework.util.StringUtils.isEmpty(dto.getMaterielId())){
                   sil.setMaterielId(dto.getMaterielName());
                }else {
                    sil.setMaterielId(dto.getMaterielId());
                }
                sil.setMaterielCode(dto.getMaterielCode());
                sil.setMaterielName(dto.getMaterielName());
                sil.setQty(dto.getQty());
                sil.setLocationId(locations.get(0).getId());
                sil.setUom(UomEnum.TAI.getName());
                sil.setLotNo1(StringUtils.isBlank(dto.getLotNo1()) ? null : dto.getLotNo1());//车架号
                sil.setLotNo2(StringUtils.isBlank(dto.getLotNo2()) ? null : dto.getLotNo2());//物料编码
                sil.setLotNo3(StringUtils.isBlank(dto.getLotNo3()) ? null : dto.getLotNo3());//颜色编码
                sil.setLotNo4(StringUtils.isBlank(dto.getLotNo4()) ? null : dto.getLotNo4());//车型代码
                insertLines.add(sil);
                sih.setStockInitLineList(insertLines);
                //导入库存
                createAndAuditStockInit(sih);
                arrayRows.getJSONObject(i).put("导入结果", "成功");
                arrayRows.getJSONObject(i).put("备注", "无");
            } catch (Exception e) {
                arrayRows.getJSONObject(i).put("导入结果", "系统异常");
                arrayRows.getJSONObject(i).put("备注", e.getMessage());
            }
        }
    }

    private int countInitStockByParam(HashMap<String, Object> params) {
        return this.baseMapper.countInitStockByParam(params);
    }

    /**
     * 更新库存量
     *
     * @param storeHouseId 仓库ID
     */
    private boolean updateStockQty(Long storeHouseId, StockInitLine ml) {
        StockProperty stockProperty = new StockProperty();
        BeanUtils.copyProperties(ml, stockProperty);
        stockProperty.setStoreHouseId(storeHouseId);
        stockService.addStock(stockProperty, "20", ml.getId());
        return true;
    }

    /**
     * 撤销库存量
     *
     * @param storeHouseId 仓库ID
     */
    private boolean cancelStockQty(Long storeHouseId, StockInitLine ml) {
        StockProperty stockProperty = new StockProperty();
        BeanUtils.copyProperties(ml, stockProperty);
        stockProperty.setStoreHouseId(storeHouseId);
        stockProperty.setLocationId(ml.getLocationId());//减少目标储位的库存
        stockService.minusStock(stockProperty, "25", ml.getId());
        return true;
    }
}
